package com.zzh.compilation.lexical;

import com.zzh.compilation.model.Token;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author  zhangzhihao Code King You Konw ?
 * @version 1.0
 * @since   未知时间
 * LaxicalAnalyzer 词法分析器
 */
public class LexicalAnalyzer {

    public static Map<Integer, String> valueTokenMap = new HashMap<>();
    static {
        valueTokenMap.put(1, "begin");
        valueTokenMap.put(2, "if");
        valueTokenMap.put(3, "then");
        valueTokenMap.put(4, "while");
        valueTokenMap.put(5, "do");
        valueTokenMap.put(6, "end");

        valueTokenMap.put(10, "变量名");

        valueTokenMap.put(18, ":=");
        valueTokenMap.put(19, ">");
        valueTokenMap.put(20, "<");
        valueTokenMap.put(21, "<>");
        valueTokenMap.put(22, "<=");
        valueTokenMap.put(24, "=");
        valueTokenMap.put(25, ";");
        valueTokenMap.put(28, "#");
        valueTokenMap.put(30, "+");
        valueTokenMap.put(31, "-");
        valueTokenMap.put(32, "*");
        valueTokenMap.put(33, "/");
        valueTokenMap.put(34, "(");
        valueTokenMap.put(35, ")");
        valueTokenMap.put(36, ",");
        valueTokenMap.put(37, ".");
        valueTokenMap.put(38, ":");
        valueTokenMap.put(39, "<-");
        valueTokenMap.put(40, "=>");
        valueTokenMap.put(41, "//");
        valueTokenMap.put(42, "/*");
        valueTokenMap.put(43, "*/");
        valueTokenMap.put(-1, "Error：未识别的符号！");
    }

    private static final List<String> keywords = new ArrayList<>();
    static {
        keywords.add("begin");
        keywords.add("if");
        keywords.add("then");
        keywords.add("while");
        keywords.add("do");
        keywords.add("end");
    }


    private static int position = 0;
    public static StringBuilder inputBuilder = new StringBuilder();
    private static int currentLineNumber = 1;

    public static List<Token> analyze() {
        List<Token> tokens = new ArrayList<>();
        String input = inputBuilder.toString();
        while (position < input.length()) {
            char currentChar = input.charAt(position);

            // 处理空白字符和换行
            if (currentChar == ' ' || currentChar == '\t' || currentChar == '\n') {
                if (currentChar == '\n') {
                    currentLineNumber++;
                }
                position++;
                continue;
            }

            // 纯数值
            if (Character.isDigit(currentChar)){
                StringBuilder word = new StringBuilder();
                while (position < input.length() && (Character.isDigit(input.charAt(position)))) {
                    word.append(input.charAt(position));
                    position++;
                }
                tokens.add(new Token(0, word.toString(), currentLineNumber));
                continue;
            }

            // 处理字符串 => 关键字 标识符变量名 （a - z和A - Z）
            if (isLetterWithoutUnderscore(currentChar)){
                StringBuilder word = new StringBuilder();
                //字符但不是中文
                while (position < input.length() && (isLetter(input.charAt(position)))){
                    word.append(input.charAt(position));
                    position++;
                }
                String wordStr = word.toString();
                //判断是不是关键字
                if (keywords.contains(wordStr)) {
                    int keywordType = getKeywordType(wordStr);
                    tokens.add(new Token(keywordType, wordStr, currentLineNumber));
                }else {//可能是 变量名
                    tokens.add(new Token(10, wordStr, currentLineNumber));
                }
                continue;
            }

            // 处理中文字符
            if (isChinese(currentChar)) {
                StringBuilder str = new StringBuilder();
                while (position < input.length() && isChinese(input.charAt(position))) {
                    str.append(input.charAt(position));
                    position++;
                }
                tokens.add(new Token(-1, "Error：中文！:" + str.toString(), currentLineNumber)); // 数字类型为 11
                continue;
            }

            // 处理运算符和其他特殊字符
            StringBuilder operator = new StringBuilder();
            operator.append(currentChar);
            if (currentChar == '>' || currentChar == '<' || currentChar == '=' || currentChar == '!' || currentChar == ':') {
                if (position + 1 < input.length()) {
                    char nextChar = input.charAt(position + 1);
                    if (nextChar == '=') {
                        operator.append(nextChar);
                        position++;
                    }
                }
            }

            //处理注释符号
            if (currentChar == '/'){
                if (position + 1 < input.length()) {
                    char nextChar = input.charAt(position + 1);
                    if (nextChar == '/') {
                        operator.append(nextChar);
                        position+=2;
                    }
                    else if (nextChar == '*') {
                        operator.append(nextChar);
                        position+=2;//直接跳过我们的/* 直接到注释内容
                    }
                }
            }

            String operatorStr = operator.toString();
            int operatorType = getOperatorType(operatorStr);

            // '//'注释的信息不存储到token中
            if (operatorType == 41) {//直接跳过注释符号的所有内容
                while (position < input.length() && !(input.charAt(position) == '\n')) {
                    position++;
                }
                if (input.charAt(position) == '\n'){
                    currentLineNumber++;
                    position++;
                }
                continue;
            }
            // '/**/'注释的信息不存储到token中
            if (operatorType == 42) {//直接跳过注释符号的所有内容
                while (position + 1 < input.length() && !(input.charAt(position) == '*') && !(input.charAt(position + 1) == '/')) {
                    //还要判断是不是换行了
                    if (input.charAt(position) == '\n'){
                        currentLineNumber++;
                    }
                    position++;
                }
                //遇到了 */就会while退出循环 此时position指向 * 的
                position+=2;//跳过两个字符
                continue;
            }

            // 注释的内容不会加入到token中会直接continue了
            tokens.add(new Token(operatorType, operatorStr, currentLineNumber));
            position++;
        }
        return tokens;
    }

    private static int getKeywordType(String keyword) {
        switch (keyword) {
            case "begin":
                return 1;
            case "if":
                return 2;
            case "then":
                return 3;
            case "while":
                return 4;
            case "do":
                return 5;
            case "end":
                return 6;
            default:
                return -1; // 未识别的关键字返回 -1
        }
    }

    private static int getOperatorType(String operator) {
        switch (operator) {
            case ":=":
                return 18;
            case ">":
                return 19;
            case "<":
                return 20;
            case "<>":
                return 21;
            case "<=":
                return 22;
            case "=":
                return 24;
            case ";":
                return 25;
            case "#":
                return 28;
            case "+":
                return 30;
            case "-":
                return 31;
            case "*":
                return 32;
            case "/":
                return 33;
            case "(":
                return 34;
            case ")":
                return 35;
            case ",":
                return 36;
            case ".":
                return 37;
            case ":":
                return 38;
            case "<-":
                return 39;
            case "=>":
                return 40;
            case "//":
                return 41;//注释符号
            case "/*":
                return 42;//注释符号
            case "*/":
                return 43;//注释符号
            default:
                return -1; // 未识别的运算符返回 -1
        }
    }

    //判断是否是中文
    public static boolean isChinese(char c) {
        return c >= '\u4e00' && c <= '\u9fff';
    }
    //判断是否为字符a-z和A-Z 以及下划线 （变量名规范）
    public static boolean isLetter(char c) {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
    }
    //判断是否为字符a-z和A-Z 除了下划线 （关键字规范）
    public static boolean isLetterWithoutUnderscore(char c) {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    }

}